// --------------------------------------------------------------------------------------------------------------------
// <copyright file="GamePadXnaExtentionMethods.cs" company="Microsoft Corporation">
// The MIT License (MIT)
// 
// Copyright (c) 2014, Microsoft Corporation
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace Microsoft.Robotics.Interaction.Xna
{
    using Microsoft.Robotics.Interaction.Runtime.Input;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Input;
    
    /// <summary>
    /// Extension methods for creating serializable versions of XNA types
    /// </summary>
    public static class GamePadXnaExtentionMethods
    {
        /// <summary>
        /// Convert GamePadAgentMessage to XNA GamePadState
        /// </summary>
        /// <param name="gpm">GamePadAgentMessage to be converted</param>
        /// <returns>XNA GamePadState</returns>
        public static GamePadState ToGamePadState(this GamePadAgentMessage gpm)
        {
            return new GamePadState(gpm.ThumbSticks.ToGamePadThumbSticks(), gpm.Triggers.ToGamePadTriggers(), gpm.Buttons.ToGamePadButtons(), gpm.DPad.ToGamePadDPad());
        }

        /// <summary>
        /// Convert GamePadState to GamePadAgentMessage
        /// </summary>
        /// <param name="gamePadState">GamePadState to be converted</param>
        /// <returns>A GamePadAgentMessage</returns>
        public static GamePadAgentMessage ToGamePadAgentMessage(this GamePadState gamePadState)
        {
            return new GamePadAgentMessage
                {
                    Buttons = gamePadState.Buttons.ToGamePadAgentButtons(),
                    DPad = gamePadState.DPad.ToGamePadAgentDPad(),
                    ThumbSticks = gamePadState.ThumbSticks.TOGamePadAgentThumbSticks(),
                    Triggers = gamePadState.Triggers.ToGamePadAgentTriggers()
                };
        }

        /// <summary>
        /// Convert XNA Vector2 to GamePadAgentVector2
        /// </summary>
        /// <param name="vector2">XNA Vector2</param>
        /// <returns>Serializable Vector2</returns>
        public static GamePadAgentMessage.GamePadAgentVector2 ToGamePadAgentVector2(this Vector2 vector2)
        {
            return new GamePadAgentMessage.GamePadAgentVector2 { X = vector2.X, Y = vector2.Y };
        }

        /// <summary>
        /// Convert GamePadAgentVector2 to XNA Vector2
        /// </summary>
        /// <param name="vector2">Serializable Vector2</param>
        /// <returns>XNA Vector2</returns>
        public static Vector2 ToVector2(this GamePadAgentMessage.GamePadAgentVector2 vector2)
        {
            return new Vector2 { X = vector2.X, Y = vector2.Y };
        }

        /// <summary>
        /// Convert XNA GamePadThumbSticks to GamePadAgentThumbSticks
        /// </summary>
        /// <param name="thumbsticks">XNA GamePadThumbSticks</param>
        /// <returns>Serializable equivalent</returns>
        public static GamePadAgentMessage.GamePadAgentThumbSticks TOGamePadAgentThumbSticks(this GamePadThumbSticks thumbsticks)
        {
            return new GamePadAgentMessage.GamePadAgentThumbSticks { Left = thumbsticks.Left.ToGamePadAgentVector2(), Right = thumbsticks.Right.ToGamePadAgentVector2() };
        }

        /// <summary>
        /// Convert GamePadAgentThumbSticks to XNA GamePadThumbSticks
        /// </summary>
        /// <param name="thumbsticks">Serializable ThumbSticks</param>
        /// <returns>XNA ThumbSticks</returns>
        public static GamePadThumbSticks ToGamePadThumbSticks(this GamePadAgentMessage.GamePadAgentThumbSticks thumbsticks)
        {
            return new GamePadThumbSticks(thumbsticks.Left.ToVector2(), thumbsticks.Right.ToVector2());
        }

        /// <summary>
        /// Convert XNA Triggers to serializable Triggers
        /// </summary>
        /// <param name="triggers">XNA Triggers</param>
        /// <returns>Serializable Triggers</returns>
        public static GamePadAgentMessage.GamePadAgentTriggers ToGamePadAgentTriggers(this GamePadTriggers triggers)
        {
            return new GamePadAgentMessage.GamePadAgentTriggers { Left = triggers.Left, Right = triggers.Right };
        }

        /// <summary>
        /// Convert Serializable Triggers to XNA Triggers
        /// </summary>
        /// <param name="triggers">Serializable Triggers</param>
        /// <returns>XNA Triggers</returns>
        public static GamePadTriggers ToGamePadTriggers(this GamePadAgentMessage.GamePadAgentTriggers triggers)
        {
            return new GamePadTriggers(triggers.Left, triggers.Right);
        }

        /// <summary>
        /// Convert XNA Buttons to Serializable Buttons
        /// </summary>
        /// <param name="buttons">XNA Buttons</param>
        /// <returns>Serializable Buttons</returns>
        public static GamePadAgentMessage.GamePadAgentButtons ToGamePadAgentButtons(this GamePadButtons buttons)
        {
            return new GamePadAgentMessage.GamePadAgentButtons
                {
                    A = buttons.A == ButtonState.Pressed,
                    B = buttons.B == ButtonState.Pressed,
                    Back = buttons.Back == ButtonState.Pressed,
                    BigButton = buttons.BigButton == ButtonState.Pressed,
                    LeftShoulder = buttons.LeftShoulder == ButtonState.Pressed,
                    LeftStick = buttons.LeftStick == ButtonState.Pressed,
                    RightShoulder = buttons.RightShoulder == ButtonState.Pressed,
                    RightStick = buttons.RightStick == ButtonState.Pressed,
                    Start = buttons.Start == ButtonState.Pressed,
                    X = buttons.X == ButtonState.Pressed,
                    Y = buttons.Y == ButtonState.Pressed
                };
        }

        /// <summary>
        /// Convert Serializable Buttons to XNA Buttons
        /// </summary>
        /// <param name="buttons">Serializable Buttons</param>
        /// <returns>XNA Buttons</returns>
        public static Buttons ToButtons(this GamePadAgentMessage.GamePadAgentButtons buttons)
        {
            Buttons xnaButtons = 0;
            xnaButtons |= buttons.A ? Microsoft.Xna.Framework.Input.Buttons.A : 0;
            xnaButtons |= buttons.B ? Microsoft.Xna.Framework.Input.Buttons.B : 0;
            xnaButtons |= buttons.Back ? Microsoft.Xna.Framework.Input.Buttons.Back : 0;
            xnaButtons |= buttons.BigButton ? Microsoft.Xna.Framework.Input.Buttons.BigButton : 0;
            xnaButtons |= buttons.LeftShoulder ? Microsoft.Xna.Framework.Input.Buttons.LeftShoulder : 0;
            xnaButtons |= buttons.LeftStick ? Microsoft.Xna.Framework.Input.Buttons.LeftStick : 0;
            xnaButtons |= buttons.RightShoulder ? Microsoft.Xna.Framework.Input.Buttons.RightShoulder : 0;
            xnaButtons |= buttons.RightStick ? Microsoft.Xna.Framework.Input.Buttons.RightStick : 0;
            xnaButtons |= buttons.Start ? Microsoft.Xna.Framework.Input.Buttons.Start : 0;
            xnaButtons |= buttons.X ? Microsoft.Xna.Framework.Input.Buttons.X : 0;
            xnaButtons |= buttons.Y ? Microsoft.Xna.Framework.Input.Buttons.Y : 0;

            return xnaButtons;
        }

        /// <summary>
        /// Convert Serializable Buttons to XNA GamePadButtons
        /// </summary>
        /// <param name="buttons">Serializable Buttons</param>
        /// <returns>XNA GamePadButtons</returns>
        public static GamePadButtons ToGamePadButtons(this GamePadAgentMessage.GamePadAgentButtons buttons)
        {
            return new GamePadButtons(buttons.ToButtons());
        }

        /// <summary>
        /// Convert XNA DPad to Serializable DPad
        /// </summary>
        /// <param name="gamePadDPad">XNA DPad</param>
        /// <returns>Serializable DPad</returns>
        public static GamePadAgentMessage.GamePadAgentDPad ToGamePadAgentDPad(this GamePadDPad gamePadDPad)
        {
            return new GamePadAgentMessage.GamePadAgentDPad
                {
                    Up = gamePadDPad.Up == ButtonState.Pressed,
                    Down = gamePadDPad.Down == ButtonState.Pressed,
                    Left = gamePadDPad.Left == ButtonState.Pressed,
                    Right = gamePadDPad.Right == ButtonState.Pressed
                };
        }

        /// <summary>
        /// Convert Serializable DPad to XNA DPad
        /// </summary>
        /// <param name="dpad">Serializable DPad</param>
        /// <returns>XNA DPad</returns>
        public static GamePadDPad ToGamePadDPad(this GamePadAgentMessage.GamePadAgentDPad dpad)
        {
            return new GamePadDPad(
                dpad.Up ? ButtonState.Pressed : ButtonState.Released,
                dpad.Down ? ButtonState.Pressed : ButtonState.Released,
                dpad.Left ? ButtonState.Pressed : ButtonState.Released,
                dpad.Right ? ButtonState.Pressed : ButtonState.Released);
        }
    }
}
